<?php
	/**
	 * Component manager implementation
	 * 
	 * Implements a basic component manager. Manages creation, deletion, and other
	 * boring functions usually required for safely using components.	 
	 * 
	 * @author     Brandon R. Stoner <brandon.stoner@gmail.com>
	 * @copyright  Copyright 2008, Monokromatic Inc.
	 * @package    Components
	 * @subpackage Managers
	 */

	/**
	 * Generic component manager
	 * 
	 * Implementation of an extremely generic component manager. Allows an
	 * application to request access to different types of functionality that
	 * it may want to make use of via standard libraries.
	 * 
	 * @author     Brandon R. Stoner <brandon.stoner@gmail.com>
	 * @copyright  Copyright 2008, Monokromatic Inc.
	 * @package    Components
	 * @subpackage Managers	 	  	 	 
	 **/	 	
	class CKromeComponentManager extends IKromeBase
	{
		/**
		 * A "friendly" name for this object.
		 * @var string
		 **/
		public    $name       = 'Krome Component Manager';

		/**
		 * An array of component objects this manager currently manages.
		 * @see IKromeComponent		 
		 * @var array
		 **/		 		
		protected $components = Array();

		/**
		 * Loads a component for use via this manager object.
		 *		 
		 * @param string $component Name of the component to be loaded
		 * @return object Reference to the created component object		 
		 **/		 		
		public function Load( $component )
		{
			$retVal = null;

				// Return an ordered array of packages, index 0 being the 'root' parent.
			$componentPackageData = $this->GetComponentPackageNameArray( $component );
			$componentClassName   = 'C';
			$componentFileName    = '';

				// Get the classname for the component, as well as it's filename...
			for ( $i=0; $i < count($componentPackageData); $i++ )
			{
					// First letter of each package should be capitolized, the rest lowercase
				$componentClassName .= strtoupper($componentPackageData[$i][0]);
				$componentClassName .= substr( $componentPackageData[$i],
				                               1,
				                               strlen($componentPackageData[$i])-1
				                             );

					// Filenames in krome are lowercase
				$componentFileName  .= strtolower( $componentPackageData[$i] ). '/';
			}

				/**
				 * @todo Use a configuration string for classnames.
				 **/				 
			$componentClassName   .= 'Component';

				// Append our filename to the system
			$componentFileName    .= $componentPackageData[ count($componentPackageData)-1 ] . KROME_FILEEXT;

				// If this component already exists...
			if ( isset($this->components[$componentClassName]) )
			{
					// ..simply return a pointer to it instead.
				$retVal = $this->components[$componentClassName];
			}

				// However, if it doesn't exist, yet...
			if ($retVal === null)
			{
					// Require the component's source file, instantiate it...
				require_once( KROME_COMPONENTDIR . $componentFileName );
				$this->components[ $componentClassName ] = new $componentClassName($this);

				$retVal = $this->components[ $componentClassName ];
			}

				// ...and set the return value.
			return $retVal;
		}

		/**
		 * Search through this object's component array and return an array of
		 * loaded components providing the requested ability.
		 * 		 
		 * @param string $ability The specific ability looking to be provided
		 * @param bool $oneshot True if we only want the first result sent back		 		 
		 * @return array Array of objects providing the requested ability		 		 
		 **/		 		
		public function FindByAbility( $ability, $oneshot=false )
		{
			$retVal = array();

			foreach ( $this->components as $val )
			{
				if ($val->HasAbility( $ability ))
				{
					if ( $oneshot === true )
					{
						$retVal = $val;
						break;
					}
					else
					{
						array_push( $retVal, $val );
					}
				}
			}
			
			return $retVal;
		}

		public function GetComponentPackageNameArray( $pComponentName )
		{
			return explode( '.', $pComponentName );
		}
	}
?>
